package model.pieces;

import java.awt.Point;
import java.util.LinkedList;
import java.util.List;

import model.Board;

/**
 * Class represents a Bishop piece in chess game. A Bishop can move in all 4 diagonal directions, until reaches another piece.  
 */
public class Bishop extends Piece {

	// protected methods

	/**
	 * Gets reference to the game board and Bishop's current position on board.
	 * Returns a list of all free positions that lay on path in any diagonal direction	 
	 */
	@Override
	protected List<Point> getAvailableFreePositions(Board gameBoard, Point srcPoint) {
		
		// initialize free possible positions list
		List<Point> freeList = new LinkedList<Point>();
		
		// initialize current row and column to search
		int currRow = srcPoint.x + getDirection();
		int currCol = srcPoint.y + getDirection();
		
		// scan forward-right path until occupied position is found or reached board's edge
		while (gameBoard.isValidPosition(currRow, currCol) && gameBoard.getPiece(currRow, currCol) == null) {
			
			// add current position
			freeList.add(new Point(currRow, currCol));
			
			// move to next position
			currRow += getDirection();
			currCol += getDirection();
		}
		
		// initialize current row and column to search
		currRow = srcPoint.x + getDirection();
		currCol = srcPoint.y - getDirection();
		
		// scan forward-left path until occupied position is found or reached board's edge
		while (gameBoard.isValidPosition(currRow, currCol) && gameBoard.getPiece(currRow, currCol) == null) {
			
			// add current position
			freeList.add(new Point(currRow, currCol));
			
			// move to next position
			currRow += getDirection();
			currCol -= getDirection();
		}
		
		// initialize current row and column to search
		currRow = srcPoint.x - getDirection();
		currCol = srcPoint.y - getDirection();
		
		// scan backward-left path until occupied position is found or reached board's edge
		while (gameBoard.isValidPosition(currRow, currCol) && gameBoard.getPiece(currRow, currCol) == null) {
			
			// add current position
			freeList.add(new Point(currRow, currCol));
			
			// move to next position
			currRow -= getDirection();
			currCol -= getDirection();
		}
		
		// initialize current row and column to search
		currRow = srcPoint.x - getDirection();
		currCol = srcPoint.y + getDirection();
		
		// scan backward-right path until occupied position is found or reached board's edge
		while (gameBoard.isValidPosition(currRow, currCol) && gameBoard.getPiece(currRow, currCol) == null) {
			
			// add current position
			freeList.add(new Point(currRow, currCol));
			
			// move to next position
			currRow -= getDirection();
			currCol += getDirection();
		}
		
		// return list of position in range found
		return freeList;
	}

	/**
	 * Gets reference to the game board and Bishop's current position on board.
	 * Returns a list of all positions holding opponent's pieces, that lay on a clear path in any diagonal direction	 
	 */
	@Override
	protected List<Point> getAvailableOpponentPositions(Board gameBoard, Point srcPoint) {
		
		// initialize list of reachable opponent's positions
		List<Point> opponentList = new LinkedList<Point>();
		
		// initialize current row and column to search
		int currRow = srcPoint.x + getDirection();
		int currCol = srcPoint.y + getDirection();
		
		// scan forward-right path until occupied position is found or reached board's edge
		while (gameBoard.isValidPosition(currRow, currCol) && gameBoard.getPiece(currRow, currCol) == null) {

			// move to next position
			currRow += getDirection();
			currCol += getDirection();
		}
		
		// stopped scanning, check if reached a piece or exceeds board
		if (gameBoard.isValidPosition(currRow, currCol)) { // still within board's limits
			if (gameBoard.getPiece(currRow, currCol) != null) { // reached a piece
				if (!super.sameTeam(gameBoard.getPiece(currRow, currCol))) { // reached opponent's piece
					// add current position
					opponentList.add(new Point(currRow, currCol));
				}
			}
		}
		
		// initialize current row and column to search
		currRow = srcPoint.x + getDirection();
		currCol = srcPoint.y - getDirection();
		
		// scan forward-left path until occupied position is found or reached board's edge
		while (gameBoard.isValidPosition(currRow, currCol) && gameBoard.getPiece(currRow, currCol) == null) {
			
			// move to next position
			currRow += getDirection();
			currCol -= getDirection();
		}
		
		// stopped scanning, check if reached a piece or exceeds board
		if (gameBoard.isValidPosition(currRow, currCol)) { // still within board's limits
			if (gameBoard.getPiece(currRow, currCol) != null) { // reached a piece
				if (!super.sameTeam(gameBoard.getPiece(currRow, currCol))) { // reached opponent's piece
					// add current position
					opponentList.add(new Point(currRow, currCol));
				}
			}
		}

		
		// initialize current row and column to search
		currRow = srcPoint.x - getDirection();
		currCol = srcPoint.y - getDirection();
		
		// scan backward-left path until occupied position is found or reached board's edge
		while (gameBoard.isValidPosition(currRow, currCol) && gameBoard.getPiece(currRow, currCol) == null) {
						
			// move to next position
			currRow -= getDirection();
			currCol -= getDirection();
		}
		
		// stopped scanning, check if reached a piece or exceeds board
		if (gameBoard.isValidPosition(currRow, currCol)) { // still within board's limits
			if (gameBoard.getPiece(currRow, currCol) != null) { // reached a piece
				if (!super.sameTeam(gameBoard.getPiece(currRow, currCol))) { // reached opponent's piece
					// add current position
					opponentList.add(new Point(currRow, currCol));
				}
			}
		}

		
		// initialize current row and column to search
		currRow = srcPoint.x - getDirection();
		currCol = srcPoint.y + getDirection();
		
		// scan backward-right path until occupied position is found or reached board's edge
		while (gameBoard.isValidPosition(currRow, currCol) && gameBoard.getPiece(currRow, currCol) == null) {
						
			// move to next position
			currRow -= getDirection();
			currCol += getDirection();
		}
		
		// stopped scanning, check if reached a piece or exceeds board
		if (gameBoard.isValidPosition(currRow, currCol)) { // still within board's limits
			if (gameBoard.getPiece(currRow, currCol) != null) { // reached a piece
				if (!super.sameTeam(gameBoard.getPiece(currRow, currCol))) { // reached opponent's piece
					// add current position
					opponentList.add(new Point(currRow, currCol));
				}
			}
		}

		
		// return list of position in range found
		return opponentList;
	}

	// public methods
	
	/**
	 * Constructor- creates a new Bishop assigned to given player
	 * @param isFirstPlayer- indicates if assigned to first player or not
	 */
	public Bishop(boolean isFirstPlayer) {
		super(isFirstPlayer);
	}

	/**
	 * Return a Bishop of the same team
	 */
	@Override
	public Piece clone() { return new Bishop(super.getPlayer()); }
}